
`include "defines.v"
//----------------------------------------------------------------
//Module Name : axi_interconnect.v
//Description of module:
// connect the masters and slaves
//----------------------------------------------------------------
//Designer:	Tang Pengyu
//Date: 2021/09/14 
//----------------------------------------------------------------

module ysyx_210195_axi_interconnect # (
//		parameter	RW_DATA_WIDTH = 64,
//		parameter	RW_ADDR_WIDTH = 64,
		parameter	AXI_DATA_WIDTH = 64,
		parameter	AXI_ADDR_WIDTH = 64,
		parameter	AXI_ID_WIDTH = 4,
		parameter	AXI_USER_WIDTH = 1
)(
//from 	master0:	instruction fetched	
		//master0 write addr
		input	clock,
		input	reset,
		
		output reg	aw_ready_0,
		input	aw_valid_0,
		input	[AXI_ADDR_WIDTH-1:0] aw_addr_0,
		input	[AXI_ID_WIDTH-1:0]	aw_id_0,			//write address channel ID
		input	[AXI_USER_WIDTH-1:0] aw_user_0,		//自定义
		input	[2:0]	aw_prot_0,				//access permissions
		input	[7:0]	aw_len_0,			//burst lenth = aw_len + 1
		input	[2:0]	aw_size_0,			//本次burst中，一次transferde的字节数
		input	[1:0]	aw_burst_0,			//burst_type
		input			aw_lock_0,
		input	[3:0]	aw_cache_0,			//memory types
		input	[3:0]	aw_qos_0,			//Quality of service identifier for a write transaction
		input	[3:0]	aw_region_0,		//多接口时用
		
		//master0 write data
		output reg	w_ready_0,
		input	w_valid_0,
		input	[AXI_DATA_WIDTH-1:0]	w_data_0,
		input	[7:0]	w_strb_0,				//标志有效位
		input	w_last_0,						//标志最后一次传输
		input	[AXI_USER_WIDTH-1:0]	w_user_0,
		
		//write response master0
		input	b_ready_0,
		output reg	b_valid_0,
		output reg	[1:0]	b_resp_0,
		output reg	[AXI_ID_WIDTH-1:0]	b_id_0,
		output reg	[AXI_USER_WIDTH-1:0]	b_user_0,
		
		//read address channel master0
		output reg	ar_ready_0,
		input	ar_valid_0,
		input	[AXI_ADDR_WIDTH-1:0]	ar_addr_0,
		input	[2:0]	ar_prot_0,
		input	[AXI_ID_WIDTH-1:0]	ar_id_0,			//read address channel identifier
		input	[AXI_USER_WIDTH-1:0]	ar_user_0,
		input	[7:0]	ar_len_0,
		input	[2:0]	ar_size_0,
		input	[1:0]	ar_burst_0,
		input			ar_lock_0,
		input	[3:0]	ar_cache_0,
		input	[3:0]	ar_qos_0,
		input	[3:0]	ar_region_0,
		
		//read data channel master0
		input	r_ready_0,
		output reg	r_valid_0,
		output reg	[1:0]	r_resp_0,
		output reg	[AXI_DATA_WIDTH-1:0]	r_data_0,
		output reg	r_last_0,
		output reg	[AXI_ID_WIDTH-1:0]	r_id_0,
		output reg	[AXI_USER_WIDTH-1:0]	r_user_0,

//from master1: read/write data		
		//master1 write addr
		output reg	aw_ready_1,
		input	aw_valid_1,
		input	[AXI_ADDR_WIDTH-1:0] aw_addr_1,
		input	[AXI_ID_WIDTH-1:0]	aw_id_1,			//write address channel ID
		input	[AXI_USER_WIDTH-1:0] aw_user_1,		//自定义
		input	[2:0]	aw_prot_1,				//access permissions
		input	[7:0]	aw_len_1,			//burst lenth = aw_len + 1
		input	[2:0]	aw_size_1,			//本次burst中，一次transferde的字节数
		input	[1:0]	aw_burst_1,			//burst_type
		input			aw_lock_1,
		input	[3:0]	aw_cache_1,			//memory types
		input	[3:0]	aw_qos_1,			//Quality of service identifier for a write transaction
		input	[3:0]	aw_region_1,		//多接口时用
		
		//master1 write data
		output reg	w_ready_1,
		input	w_valid_1,
		input	[AXI_DATA_WIDTH-1:0]	w_data_1,
		input	[7:0]	w_strb_1,				//标志有效位
		input	w_last_1,						//标志最后一次传输
		input	[AXI_USER_WIDTH-1:0]	w_user_1,
		
		//write response master1
		input	b_ready_1,
		output reg	b_valid_1,
		output reg	[1:0]	b_resp_1,
		output reg	[AXI_ID_WIDTH-1:0]	b_id_1,
		output reg	[AXI_USER_WIDTH-1:0]	b_user_1,
		
		//read address channel master1
		output reg	ar_ready_1,
		input	ar_valid_1,
		input	[AXI_ADDR_WIDTH-1:0]	ar_addr_1,
		input	[2:0]	ar_prot_1,
		input	[AXI_ID_WIDTH-1:0]	ar_id_1,			//read address channel identifier
		input	[AXI_USER_WIDTH-1:0]	ar_user_1,
		input	[7:0]	ar_len_1,
		input	[2:0]	ar_size_1,
		input	[1:0]	ar_burst_1,
		input			ar_lock_1,
		input	[3:0]	ar_cache_1,
		input	[3:0]	ar_qos_1,
		input	[3:0]	ar_region_1,
		
		//read data channel master1
		input	r_ready_1,
		output reg	r_valid_1,
		output reg	[1:0]	r_resp_1,
		output reg	[AXI_DATA_WIDTH-1:0]	r_data_1,
		output reg	r_last_1,
		output reg	[AXI_ID_WIDTH-1:0]	r_id_1,
		output reg	[AXI_USER_WIDTH-1:0]	r_user_1,		


//to slave
		//MASTER write addr
		input	aw_ready_i,			//slave -> master,ready to receive write address
		output	reg aw_valid_o,			//master -> slave,write address valid
		output	reg [AXI_ADDR_WIDTH-1:0] aw_addr_o,		//write sddress
		output	reg [AXI_ID_WIDTH-1:0]	aw_id_o,			//write address channel ID
		output	reg [AXI_USER_WIDTH-1:0] aw_user_o,		//自定义
		output	reg [2:0]	aw_prot_o,				//access permissions
		output	reg [7:0]	aw_len_o,			//burst lenth = aw_len + 1
		output	reg [2:0]	aw_size_o,			//本次burst中，一次transferde的字节数
		output	reg [1:0]	aw_burst_o,			//burst_type
		output	reg		aw_lock_o,
		output	reg [3:0]	aw_cache_o,			//memory types
		output	reg [3:0]	aw_qos_o,			//Quality of service identifier for a write transaction
		output	reg [3:0]	aw_region_o,		//多接口时用
		
		//master write data
		input	w_ready_i,
		output	reg w_valid_o,
		output	reg [AXI_DATA_WIDTH-1:0]	w_data_o,
		output	reg [7:0]	w_strb_o,				//标志有效位
		output	reg w_last_o,						//标志最后一次传输
		output	reg [AXI_USER_WIDTH-1:0]	w_user_o,
		
		//write response
		output	reg b_ready_o,
		input	b_valid_i,
		input	[1:0]	b_resp_i,
		input	[AXI_ID_WIDTH-1:0]	b_id_i,
		input	[AXI_USER_WIDTH-1:0]	b_user_i,
		
		//read address channel
		input	ar_ready_i,
		output	reg ar_valid_o,
		output	reg [AXI_ADDR_WIDTH-1:0]	ar_addr_o,
		output	reg [2:0]	ar_prot_o,
		output	reg [AXI_ID_WIDTH-1:0]	ar_id_o,			//read address channel identifier
		output	reg [AXI_USER_WIDTH-1:0]	ar_user_o,
		output	reg [7:0]	ar_len_o,
		output	reg [2:0]	ar_size_o,
		output	reg [1:0]	ar_burst_o,
		output	reg		ar_lock_o,
		output	reg [3:0]	ar_cache_o,
		output	reg [3:0]	ar_qos_o,
		output	reg [3:0]	ar_region_o,
		
		//read data channel
		output	reg r_ready_o,
		input	r_valid_i,
		input	[1:0]	r_resp_i,
		input	[AXI_DATA_WIDTH-1:0]	r_data_i,
		input	r_last_i,
		input	[AXI_ID_WIDTH-1:0]	r_id_i,
		input	[AXI_USER_WIDTH-1:0]	r_user_i

);

reg		master_valid_0;
reg		master_valid_1;

wire	[1:0]	valid1_valid0;
assign	valid1_valid0 = {master_valid_1,master_valid_0};

reg		r_ready_0_r;
reg		r_ready_1_r;

//将r_ready_o延迟一拍
always @(posedge clock)	begin
	if(reset)	begin
		r_ready_0_r <= 1'b0;
		r_ready_1_r <= 1'b0;
	end
	else	begin
		r_ready_0_r <= r_ready_0;
		r_ready_1_r <= r_ready_1;
	end
end

wire	valid_begin_0;			//posedge work
assign	valid_begin_0 = ar_valid_0 | aw_valid_0;
wire	valid_begin_1;
assign	valid_begin_1 = ar_valid_1 | aw_valid_1;

wire	valid_end_0;			//negedge work
assign	valid_end_0 = !(r_ready_0_r | b_ready_0);
wire	valid_end_1;
assign	valid_end_1 = !(r_ready_1_r | b_ready_1);

reg		valid_begin_0_r;
//reg		valid_begin_0_r1;
reg		valid_end_0_r;
reg		valid_begin_1_r;
//reg		valid_begin_1_r1;
reg		valid_end_1_r;
always @(posedge clock)	begin
	if(reset)	begin
		valid_begin_0_r <= 1'b0;
//		valid_begin_0_r1 <= 1'b0;
		valid_end_0_r <= 1'b0;
		valid_begin_1_r <= 1'b0;
//		valid_begin_1_r1 <= 1'b0;
		valid_end_1_r <= 1'b0;
	end
	else	begin
		valid_begin_0_r <= valid_begin_0;
//		valid_begin_0_r1 <= valid_begin_0_r;
		valid_end_0_r <= valid_end_0;
		valid_begin_1_r <= valid_begin_1;
//		valid_begin_1_r1 <= valid_begin_1_r;
		valid_end_1_r <= valid_end_1;
	
	end
end
wire	valid_begin_0_en;
wire	valid_end_0_en;
wire	valid_begin_1_en;
wire	valid_end_1_en;
assign	valid_begin_0_en = valid_begin_0 & (~valid_begin_0_r);
assign	valid_end_0_en = valid_end_0 & (~valid_end_0_r);
assign	valid_begin_1_en = valid_begin_1 & (~valid_begin_1_r);
assign	valid_end_1_en = valid_end_1 & (~valid_end_1_r);

//always @(posedge valid_begin_0 or posedge valid_end_0)	begin
always @(posedge clock)	begin
	if(reset)
		master_valid_0 <= 1'b0;
	else if(valid_begin_0_en)
		master_valid_0 <= 1'b1;
	else if(valid_end_0_en)
		master_valid_0 <= 1'b0;
end

//always @(posedge valid_begin_1 or posedge valid_end_1)	begin
always @(posedge clock)	begin
	if(reset)
		master_valid_1 <= 1'b0;
	if(valid_begin_1_en)
		master_valid_1 <= 1'b1;
	else if(valid_end_1_en)
		master_valid_1 <= 1'b0;
end

//固定优先级
always @(*)	begin
	case(valid1_valid0)
		2'b10,2'b11:	begin			//ls_valid,all valid
			//to slave
			aw_valid_o = aw_valid_1;
			aw_addr_o = aw_addr_1;
			aw_id_o = aw_id_1;
			aw_user_o = aw_user_1;
			aw_prot_o = aw_prot_1;
			aw_len_o = aw_len_1;
			aw_size_o = aw_size_1;
			aw_burst_o = aw_burst_1;
			aw_lock_o = aw_lock_1;
			aw_cache_o = aw_cache_1;
			aw_qos_o = aw_qos_1;
			aw_region_o = aw_region_1;
			
			w_valid_o = w_valid_1;
			w_data_o = w_data_1;
			w_strb_o = w_strb_1;
			w_last_o = w_last_1;
			w_user_o = w_user_1;
			
			b_ready_o = b_ready_1;
			
			ar_valid_o = ar_valid_1;
			ar_addr_o = ar_addr_1;
			ar_prot_o = ar_prot_1;
			ar_id_o = ar_id_1;
			ar_user_o = ar_user_1;
			ar_len_o = ar_len_1;
			ar_size_o = ar_size_1;
			ar_burst_o = ar_burst_1;
			ar_lock_o = ar_lock_1;
			ar_cache_o = ar_cache_1;
			ar_qos_o = ar_qos_1;
			ar_region_o = ar_region_1;
			
			r_ready_o = r_ready_1;
			
			//to master0
			aw_ready_0 = 1'b0;
			
			w_ready_0 = 1'b0;
			
			b_valid_0 = 1'b0;
			b_resp_0 = 2'b00;
			b_id_0 = {AXI_ID_WIDTH{1'b0}};
			b_user_0 = {AXI_USER_WIDTH{1'b0}};
			
			ar_ready_0 = 1'b0;
			
			r_valid_0 = 1'b0;
			r_resp_0 = 2'b00;
			r_data_0 = {AXI_DATA_WIDTH{1'b0}};
			r_last_0 = 1'b0;
			r_id_0 = {AXI_ID_WIDTH{1'b0}};
			r_user_0 = {AXI_USER_WIDTH{1'b0}};
			
			//to master1
			aw_ready_1 = aw_ready_i;
			
			w_ready_1 = w_ready_i;
			
			b_valid_1 = b_valid_i;
			b_resp_1 = b_resp_i;
			b_id_1 = b_id_i;
			b_user_1 = b_user_i;
			
			ar_ready_1 = ar_ready_i;
			
			r_valid_1 = r_valid_i;
			r_resp_1 = r_resp_i;
			r_data_1 = r_data_i;
			r_last_1 = r_last_i;
			r_id_1 = r_id_i;
			r_user_1 = r_user_i;
			
		end
			
		2'b01:		begin					//if valid
		//to slave
			aw_valid_o = aw_valid_0;
			aw_addr_o = aw_addr_0;
			aw_id_o = aw_id_0;
			aw_user_o = aw_user_0;
			aw_prot_o = aw_prot_0;
			aw_len_o = aw_len_0;
			aw_size_o = aw_size_0;
			aw_burst_o = aw_burst_0;
			aw_lock_o = aw_lock_0;
			aw_cache_o = aw_cache_0;
			aw_qos_o = aw_qos_0;
			aw_region_o = aw_region_0;
			
			w_valid_o = w_valid_0;
			w_data_o = w_data_0;
			w_strb_o = w_strb_0;
			w_last_o = w_last_0;
			w_user_o = w_user_0;
			
			b_ready_o = b_ready_0;
			
			ar_valid_o = ar_valid_0;
			ar_addr_o = ar_addr_0;
			ar_prot_o = ar_prot_0;
			ar_id_o = ar_id_0;
			ar_user_o = ar_user_0;
			ar_len_o = ar_len_0;
			ar_size_o = ar_size_0;
			ar_burst_o = ar_burst_0;
			ar_lock_o = ar_lock_0;
			ar_cache_o = ar_cache_0;
			ar_qos_o = ar_qos_0;
			ar_region_o = ar_region_0;
			
			r_ready_o = r_ready_0;
			
		//to master0
			aw_ready_0 = aw_ready_i;
			
			w_ready_0 = w_ready_i;
			
			b_valid_0 = b_valid_i;
			b_resp_0 = b_resp_i;
			b_id_0 = b_id_i;
			b_user_0 = b_user_i;
			
			ar_ready_0 = ar_ready_i;
			
			r_valid_0 = r_valid_i;
			r_resp_0 = r_resp_i;
			r_data_0 = r_data_i;
			r_last_0 = r_last_i;
			r_id_0 = r_id_i;
			r_user_0 = r_user_i;
			
		//to master1
			aw_ready_1 = 1'b0;
			
			w_ready_1 = 1'b0;
			
			b_valid_1 = 1'b0;
			b_resp_1 = 2'b00;
			b_id_1 = {AXI_ID_WIDTH{1'b0}};
			b_user_1 = {AXI_USER_WIDTH{1'b0}};
			
			ar_ready_1 = 1'b0;
			
			r_valid_1 = 1'b0;
			r_resp_1 = 2'b00;
			r_data_1 = {AXI_DATA_WIDTH{1'b0}};
			r_last_1 = 1'b0;
			r_id_1 = {AXI_ID_WIDTH{1'b0}};
			r_user_1 = {AXI_USER_WIDTH{1'b0}};
			
		end
		2'b00:		begin
		//to slave
			aw_valid_o = 1'b0;
			aw_addr_o = {AXI_ADDR_WIDTH{1'b1}};
			aw_id_o = {AXI_ID_WIDTH{1'b1}};
			aw_user_o = {AXI_USER_WIDTH{1'b1}};
			aw_prot_o = 3'b000;
			aw_len_o = 8'h00;
			aw_size_o = 3'b000;
			aw_burst_o = 2'b01;
			aw_lock_o = 1'b0;
			aw_cache_o = 4'h0;
			aw_qos_o = 4'h0;
			aw_region_o = 4'h0;
			
			w_valid_o = 1'b0;
			w_data_o = {AXI_DATA_WIDTH{1'b0}};
			w_strb_o = 8'h00;
			w_last_o = 1'b0;
			w_user_o = {AXI_USER_WIDTH{1'b0}};
			
			b_ready_o = 1'b0;
			
			ar_valid_o = 1'b0;
			ar_addr_o = {AXI_ADDR_WIDTH{1'b0}};
			ar_prot_o = 3'b000;
			ar_id_o = {AXI_ID_WIDTH{1'b0}};
			ar_user_o = {AXI_USER_WIDTH{1'b0}};
			ar_len_o = 8'h00;
			ar_size_o = 3'b000;
			ar_burst_o = 2'b00;
			ar_lock_o = 1'b0;
			ar_cache_o = 4'h0;
			ar_qos_o = 4'h0;
			ar_region_o = 4'h0;
			
			r_ready_o = 1'b0;
			
			
			//to master0
			aw_ready_0 = 1'b0;
			
			w_ready_0 = 1'b0;
			
			b_valid_0 = 1'b0;
			b_resp_0 = 2'b00;
			b_id_0 = {AXI_ID_WIDTH{1'b0}};
			b_user_0 = {AXI_USER_WIDTH{1'b0}};
			
			ar_ready_0 = 1'b0;
			
			r_valid_0 = 1'b0;
			r_resp_0 = 2'b00;
			r_data_0 = {AXI_DATA_WIDTH{1'b0}};
			r_last_0 = 1'b0;
			r_id_0 = {AXI_ID_WIDTH{1'b0}};
			r_user_0 = {AXI_USER_WIDTH{1'b0}};
			
		//to master1
			aw_ready_1 = 1'b0;
			
			w_ready_1 = 1'b0;
			
			b_valid_1 = 1'b0;
			b_resp_1 = 2'b00;
			b_id_1 = {AXI_ID_WIDTH{1'b0}};
			b_user_1 = {AXI_USER_WIDTH{1'b0}};
			
			ar_ready_1 = 1'b0;
			
			r_valid_1 = 1'b0;
			r_resp_1 = 2'b00;
			r_data_1 = {AXI_DATA_WIDTH{1'b0}};
			r_last_1 = 1'b0;
			r_id_1 = {AXI_ID_WIDTH{1'b0}};
			r_user_1 = {AXI_USER_WIDTH{1'b0}};
			
		end	
		
		






	endcase
end

endmodule
